package com.msb.push.mq;

import com.alibaba.fastjson2.JSON;
import com.msb.common.constart.RabbitMQConstants;
import com.msb.common.model.StandardReport;
import com.msb.push.config.RabbitMQConfig;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

/**
 * @Author: lmf
 * @Create: 2025/3/20 13:28
 * @module
 */
@Component
@Slf4j
public class PushReportListener {

    // 重试的时间间隔。
    private final int[] delayTime = {0, 10000, 15000, 30000, 30000};

    @Resource
    private RestTemplate restTemplate;

    @Resource
    private RabbitTemplate rabbitTemplate;


    @RabbitListener(queues = RabbitMQConstants.SMS_SEND_CLIENT)
    public void consume(StandardReport report, Channel channel, Message message) throws IOException {


        log.info("收到状态报告 report={}", report);
        // 获取客户回调地址
        String callbackUrl = report.getCallbackUrl();
        if (StringUtils.isEmpty(callbackUrl)) {
            log.info("回调地址为空 callbackUrl = {}", report);
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        }
        // 发送状态报告
        boolean flag = pushReport(report);

        isResEnd(report, flag);

        // 成功进行ack
        log.info("消息被消费 report={}", report);
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
    }

    @RabbitListener(queues = RabbitMQConfig.DELAYED_QUEUE)
    public void delayedConsume(StandardReport report, Channel channel, Message message) throws IOException {
        // 打印当前进入时间吧时间装换成 yyyy-mm-dd hh:mm:ss
        log.info("延迟消息当前进入时间={}", LocalDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME));
        // 发送状态报告
        boolean flag = pushReport(report);
        isResEnd(report, flag);

        // 成功进行ack
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
    }

    /**
     * 判断是否重试结束
     */
    private void isResEnd(StandardReport report, boolean flag) {
        // 失败进行重试
        if (!flag) {
            log.info("进入重试阶段 report={}", report);
            if (report.getRetryCount() == null) {
                report.setRetryCount(0);
            }
            if (report.getRetryCount() < delayTime.length - 1) {
                report.setRetryCount(report.getRetryCount() + 1);
                rabbitTemplate.convertAndSend(RabbitMQConfig.DELAYED_EXCHANGE, "", report, new MessagePostProcessor() {
                    @Override
                    public Message postProcessMessage(Message message) throws AmqpException {
                        log.info("第{}次发送状态报告消息到延迟队列", report.getRetryCount());
                        // 设置延迟时间
                        message.getMessageProperties().setDelay(delayTime[report.getRetryCount()]);

                        return message;
                    }
                });
            } else {
                log.info("重试结束==================================");
            }
        }
    }

    private boolean pushReport(StandardReport report) {
        boolean flag = false;
        // 地址前缀
        String url = "http://";

        //声明发送的参数
        String body = JSON.toJSONString(report);

//        // 声明restTemplate的模板代码
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);

        try {
            log.info("发送状态报告请求给客户端 url={},body={}", url + report.getCallbackUrl(), body);
            String result = restTemplate.postForObject(url + report.getCallbackUrl(), new HttpEntity<>(body,
                            httpHeaders),
                    String.class);
            String SUCCESS = "success";
            flag = SUCCESS.equals(result);
        } catch (RestClientException e) {
            log.info("发送状态报告失败 report={}", report);
        }

        // 返回结果
        return flag;
    }
}
